package testcase.iotest;

import junit.framework.TestCase;
import io.*;
import io.command.*;
import io.command.result.*;
import card.Card;
import card.Cardset;

public class IOManagerUnitTest extends TestCase {

	class IOCommandFactoryStub extends IOCommandFactory {
		private int intResult;
		private char charResult;
		private boolean secondRun;

		public IOCommandFactoryStub() {
			this('0', 0);
		}

		public IOCommandFactoryStub(int intResult) {
			this('0', intResult);
		}

		public IOCommandFactoryStub(char charResult) {
			this(charResult, 0);
		}

		public IOCommandFactoryStub(char charResult, int intResult) {
			super(null);
			this.charResult = charResult;
			this.intResult = intResult;
			this.secondRun = false;
		}

		public IOCommand createHandDisplayCommand(Cardset c, String playerName) {
			return new IOCommandStub();
		}

		public IOCommand createCardInputCommand(Cardset c) {
			if (!secondRun) {
				secondRun = true;
				return new IOCommandStub(new IOIntResult(intResult));
			}
			return new IOCommandStub(new IOIntResult(-1));
		}

		public IOCommand createEndGameMessageCommand() {
			return new IOCommandStub();
		}

		public IOCommand createNewRoundMessageCommand(String newRoundStarterName) {
			return new IOCommandStub();
		}

		public IOCommand createConfirmPlayCommand(Cardset play) {
			return new IOCommandStub(new IOCharResult(charResult));
		}

		public IOCommand createNotBiggerPlayMessageCommand() {
			return new IOCommandStub();
		}

		public IOCommand createContinueGameCommand(String winner) {
			return new IOCommandStub(new IOCharResult(charResult));
		}

		public IOCommand createEndApplicationMessageCommand() {
			return new IOCommandStub();
		}

		public IOCommand createPlayerLandlordRatingCommand(String playerName,
				Cardset hand) {
			return new IOCommandStub(new IOIntResult(intResult));
		}
	}

	static class CommandExecutionCheck {
		public static boolean executed;

		static {
			executed = false;
		}

		public static void reset() {
			executed = false;
		}

		public static boolean getExecuted() {
			return executed;
		}

		public static void executed() {
			executed = true;
		}

	}

	class IOCommandStub extends IOCommand {

		private IOResult resultStub;

		public IOCommandStub() {
			super(null);
		}

		public IOCommandStub(IOResult resultStub) {
			super(null);
			this.resultStub = resultStub;
		}

		@Override
		public IOResult execute() {
			CommandExecutionCheck.executed();
			return resultStub;
		}
	}

	class IOStub implements IIO {
		public String lastPrint;

		@Override
		public String getNextInput() {
			return null;
		}

		@Override
		public void println() {
		}

		@Override
		public void println(String s) {
			lastPrint = s;
		}

		@Override
		public void print(String s) {
			lastPrint = s;
		}

		@Override
		public void print(Card c, int index) {
		}

		@Override
		public void print(Cardset cs) {
		}
	}

	public void testPlayerSelectCards() {
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub(1));

		Cardset cards = new Cardset(3);
		Card card1 = new Card('d', '3');
		Card card2 = new Card('d', '4');
		cards.add(card1);
		cards.add(card2);

		Cardset result = ioManager.ioPlayerSelectCards(cards, "test");
		assertEquals(result.count(), 1);
		assertEquals(true, result.getCard(0).compare(card2));
	}

	public void testEndGameMessage() {
		CommandExecutionCheck.reset();
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub());
		ioManager.ioEndGameMessage();

		assertEquals(true, CommandExecutionCheck.getExecuted());
	}

	public void testNewRoundMessage() {
		CommandExecutionCheck.reset();
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub());
		ioManager.ioNewRoundMessage("test");

		assertEquals(true, CommandExecutionCheck.getExecuted());
	}

	public void testNotBiggerPlayMessage() {
		CommandExecutionCheck.reset();
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub());
		ioManager.ioNotBiggerPlayMessage();

		assertEquals(true, CommandExecutionCheck.getExecuted());
	}

	public void testConfirmPlay() {
		CommandExecutionCheck.reset();
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub('y'));
		char result = ioManager.ioConfirmPlay(new Cardset(3));

		assertEquals(result, 'y');
	}

	public void testContinueGame() {
		CommandExecutionCheck.reset();
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub('y'));
		char result = ioManager.ioContinueGame("test");

		assertEquals(result, 'y');
	}

	public void testEndApplicationMessage() {
		CommandExecutionCheck.reset();
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub());
		ioManager.ioEndApplicationMessage();

		assertEquals(true, CommandExecutionCheck.getExecuted());
	}

	public void testPlayerLandlordRating() {
		CommandExecutionCheck.reset();
		IOManager ioManager = new IOManager(new IOStub(),
				new IOCommandFactoryStub(2));
		int result = ioManager.ioPlayerLandlordRating("test", new Cardset(3));

		assertEquals(2, result);
	}

	public void testIOManagerCreation() {
		boolean succeed = true;

		try {
			IOManager ioManager = new IOManager();
			ioManager.ioEndApplicationMessage();
		} catch (Exception c) {
			succeed = false;
		}

		assertEquals(true, succeed);

	}

}
